﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using UniversityRatingSystem.Models;
using UniversityRatingSystem.DependencyInjector;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity.EntityFramework;

namespace UniversityRatingSystem.Controllers
{
    [Authorize(Roles = "administrator")]
    public class AdminController : Controller
    {
        private UserManager<ApplicationUser> userManager;
        private RoleManager<IdentityRole> roleManager;
        private ApplicationDbContext appDb;

        public AdminController()
        {
            userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(DI.Singleton.ApplicationDbContext));
            appDb = DI.Singleton.ApplicationDbContext;
            roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(appDb));
        }

        //
        // GET: /Admin/
        public ActionResult Index()
        {
            return View(appDb.Users.ToList());
        }

        //
        // GET: /Admin/Create
        public ActionResult Create()
        {
            return View();
        }

        //
        // POST: /Admin/Create
        [HttpPost]
        public async Task<ActionResult> Create(AdminRegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser()
                {
                    UserName = model.UserName,
                    FirstName = model.FirstName,
                    LastName = model.LastName,
                    Patronymic = model.Patronymic,
                    Group = model.Group,
                    Confirmed = true,
                    Email = model.Email
                };
                var result = await userManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    var addedUser = await userManager.FindByNameAsync(model.UserName);
                    foreach(var i in model.Role.Split(' '))
                    {
                        if (!userManager.IsInRole(addedUser.Id, i))
                        {
                            if (!roleManager.RoleExists(i))
                                roleManager.Create(new IdentityRole(i));
                            await userManager.AddToRoleAsync(addedUser.Id, i);
                        }
                    }
                    if (!model.Role.Contains("administrator"))
                    {
                        var person = new Person();
                        var groupQuery = from c in appDb.Groups where c.Name == user.Group select c;
                        if (groupQuery.LongCount() <= 0)
                        {
                            //Create new group
                            var group = appDb.Groups.Add(new Group()
                            {
                                Name = user.Group,
                            });
                        }
                        else
                        {
                            //Link to existing group
                            person.GroupId = groupQuery.First<Group>().GroupId;
                        }
                        person.AspUser = addedUser;
                        appDb.Persons.Add(person);
                        appDb.SaveChanges();
                    }
                    return RedirectToAction("Index", "Admin");
                }
                else
                {
                    foreach (var error in result.Errors)
                    {
                        ModelState.AddModelError("", error);
                    }
                }
            }
            return View(model);
        }

        //
        // GET: /Admin/Edit/5
        public ActionResult Edit(string id)
        {
            ApplicationUser user = userManager.FindById(id);
            //Map onto AdminRegisterModel
            string roles = "";
            foreach (var i in userManager.GetRoles(id))
            {
                roles = roles + i + " ";
            }
            roles = roles.Trim();
            return View(new AdminEditUserViewModel()
            {
                Email = user.Email,
                FirstName = user.FirstName,
                Group = user.Group,
                LastName = user.LastName,
                Patronymic = user.Patronymic,
                UserName = user.UserName,
                Role = roles
            });
        }

        //
        // POST: /Admin/Edit/5
        [HttpPost]
        public async Task<ActionResult> Edit(string id, AdminEditUserViewModel model)
        {
            if(ModelState.IsValid)
            {
                var user = await userManager.FindByIdAsync(id);
                user.Email = model.Email;
                user.FirstName = model.FirstName;
                user.Group = model.Group;
                user.LastName = model.LastName;
                user.Patronymic = model.Patronymic;
                user.UserName = model.UserName;
                foreach(var i in model.Role.Split(' '))
                {
                    if (!userManager.IsInRole(id, i))
                    {
                        if (!roleManager.RoleExists(i))
                            roleManager.Create(new IdentityRole(i));
                        await userManager.AddToRoleAsync(id, i);
                    }
                }
                await userManager.UpdateAsync(user);
            }
            return View(model);
        }

        //
        // GET: /Admin/Delete/5
        public ActionResult Delete(string id)
        {
            var user = userManager.FindById(id);
            if(user == null)
            {
                user = appDb.Users.First(a => a.Id == id);
            }
            if (user.Person != null)
            {
                appDb.Marks.RemoveRange(user.Person.Marks);
                appDb.Documents.RemoveRange(user.Person.Documents);
                appDb.Persons.Remove(user.Person);
            }
            appDb.SaveChanges();
            userManager.Delete(user);
            return RedirectToAction("Index");
        }

        //
        // POST: /Admin/Delete/5
        [HttpPost]
        public ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                // TODO: Add delete logic here

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
    }
}
